#!/usr/bin/python
# -*- coding: UTF-8 -*-
from tkinter import *
import _thread
import tkinter.messagebox
from tkinter.scrolledtext import ScrolledText
import tkinter.font as tFont
import tkinter.filedialog
import requests
import time
import os
import json
def getTime():
    return time.strftime("[%Y-%m-%d %H:%M:%S]", time.localtime())
def getTime2():
    return time.strftime("%Y%m%d%H%M%S", time.localtime())
def about():
    tkinter.messagebox.showinfo('关于', 'OJ题库爬虫 V1.0.2\nBy VegeTable Dev Team')
def wannahelp():
    tkinter.messagebox.showinfo('有问题？', '首先你需要把该填的全填了\n网址就填一个OJ题目查看页面的网址，题目编号用[:id]代替\n例如http://www.hustoj.com/oj/problem.php?id=[:id]')
def getJson():
    fname = tkinter.filedialog.askopenfilename(title='选择JSON文件', filetypes=[('JSON', '.json'), ('All Files', '*')])
    proLog.insert("end", getTime()+"从"+fname+"导入配置"+"\n")
    try:
        file = open(fname, "r")
        gJSON = file.read()
        file.close()
        gJSON=json.loads(gJSON)
    except Exception:
        proLog.insert("end", getTime())
        proLog.insert("end", "读取错误"+Exception, "tagError")
        proLog.insert("end", "\n")
    else:
        proLog.insert("end", getTime())
        proLog.insert("end", "读取成功", "tagSuccess")
        proLog.insert("end", "\n")
        hustojurl.delete(0, "end")
        defaultUrl.set(gJSON["ojurl"])
        startId.delete(0, "end")
        defaultsID.set(gJSON["startId"])
        endId.delete(0, "end")
        defaulteId.set(gJSON["endId"])
    proLog.see(END)
def saveJson():
    fname = tkinter.filedialog.asksaveasfilename(title=u'保存为json', filetypes=[("JSON", ".json")])
    fname = str(fname)+".json"
    proLog.insert("end", getTime()+"保存当前配置到"+fname+"\n")
    try:
        file = open(fname, "w")
        file.write("{\"ojurl\":\""+hustojurl.get()+"\",\"startId\":\""+startId.get()+"\",\"endId\":\""+endId.get()+"\"}")
        file.close()
    except Exception:
        proLog.insert("end", getTime())
        proLog.insert("end", "写入错误", "tagError")
        proLog.insert("end", "\n")
    else:
        proLog.insert("end", getTime())
        proLog.insert("end", "写入成功", "tagSuccess")
        proLog.insert("end", "\n")
    proLog.see(END)
def testedOJ():
    tkinter.messagebox.showinfo('支持的OJ', '支持OJ：各版本Hustoj，各版本Syzoj，POJ，洛谷\n不支持OJ：各版本Qduoj')
def mkadir(path):
    path=path.strip()
    path=path.rstrip("\\")
    isExists=os.path.exists(path)
    if not isExists:
        try:
            os.mkdir(path) 
        except Exception:
            proLog.insert("end", getTime())
            proLog.insert("end", "创建目录"+path+"失败", "tagError")
            proLog.insert("end", "\n")
        else:
            proLog.insert("end", getTime())
            proLog.insert("end", "创建目录"+path+"成功", "tagSuccess")
            proLog.insert("end", "\n")
        return True
    else:
        proLog.insert("end", getTime())
        proLog.insert("end", path+"已经存在", "tagWarn")
        proLog.insert("end", "\n")
        return False
def getProblem(url, id, fdler):
    print(id)
    proLog.insert("end", getTime())
    proLog.insert("end", "开始爬取P"+str(id))
    proLog.insert("end", "\n")
    realUrl = url.replace("[:id]", str(id))
    proLog.insert("end", getTime())
    proLog.insert("end", "请求URL"+realUrl)
    proLog.insert("end", "\n")
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4101.0 Safari/537.36 Edg/83.0.474.0",
        "Referer": "https://www.luogu.com.cn/problem/list"
    }
    getInfo = requests.get(realUrl, headers=headers)
    getInfo.encoding="utf-8"
    if (getInfo.status_code!=200):
        proLog.insert("end", getTime())
        proLog.insert("end", "错误，服务器返回"+str(getInfo.status_code)+"错误", "tagError")
        proLog.insert("end", "\n")
        return;
    proLog.insert("end", getTime())
    proLog.insert("end", "写入文件"+fdler+"\\"+str(id)+".html")
    proLog.insert("end", "\n")
    print(getInfo.content)
    try:
        file = open(fdler+"\\"+str(id)+".html", "wb+")
        file.write(getInfo.content)
        file.close()
    except Exception:
        proLog.insert("end", getTime())
        proLog.insert("end", "写入错误", "tagError")
        proLog.insert("end", "\n")
    else:
        proLog.insert("end", getTime())
        proLog.insert("end", "写入成功", "tagSuccess")
        proLog.insert("end", "\n")
    proLog.see(END)
    time.sleep(0.1)
def startGet():
    if (len(hustojurl.get())==0):
        proLog.insert("end", "[错误]没有填写hustoj地址\n", "tagError")
        return;
    if (len(startId.get())==0):
        proLog.insert("end", "[错误]没有填写开始题号\n", "tagError")
        return;
    if (len(endId.get())==0):
        proLog.insert("end", "[错误]没有填写结束题号\n", "tagError")
        return;
    if ((int)(startId.get()) > (int)(endId.get())):
        proLog.insert("end", "[错误]开始题号大于结束题号\n", "tagError")
        return;
    if (hustojurl.get().find("hustoj.com")!=-1):
        proLog.insert("end", "[警告]打算尝试爬取hustoj官方网站，不怕zhblue打你吗\n", "tagWarn")
    if (hustojurl.get().find("luogu.com.cn")!=-1):
        proLog.insert("end", "[警告]打算尝试爬取洛谷，可能会返回404\n", "tagWarn")
    fdder=getTime2()
    mkadir(fdder)
    proLog.insert("end", getTime())
    proLog.insert("end", "开始爬取"+hustojurl.get())
    proLog.insert("end", "\n")
    for i in range((int)(startId.get()), (int)(endId.get())+1):
        getProblem(hustojurl.get(), i, fdder)
    proLog.insert("end", getTime()+"Done\n", "tagInfo")
def qaq():
    _thread.start_new_thread(startGet, ())
root = Tk()
root.title("OJ题库爬虫")
menubar = Menu(root)
helpmenu = Menu(menubar, tearoff=0)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="文件",menu=filemenu)
filemenu.add_command(label='导入json', command=getJson)
filemenu.add_command(label='另存为json..', command=saveJson)
menubar.add_cascade(label="帮助",menu=helpmenu)
helpmenu.add_command(label='帮助', command=wannahelp)
helpmenu.add_command(label='关于', command=about)
helpmenu.add_command(label='支持的OJ', command=testedOJ)
proLog = ScrolledText(root, height=10)
proLog.grid(row=0, columnspan=2)
proLog.tag_add('tagError','1.7','1.12')
proLog.tag_config('tagError', foreground='red')
proLog.tag_add('tagInfo','1.7','1.12')
proLog.tag_config('tagInfo', foreground='blue')
proLog.tag_add('tagWarn','1.7','1.12')
proLog.tag_config('tagWarn', foreground='orange')
proLog.tag_add('tagSuccess','1.7','1.12')
proLog.tag_config('tagSuccess', foreground='green')
Label(root,text="OJ题库爬虫", font=("微软雅黑",20)).grid(row=1,columnspan=2)
Label(root,text="网址", font=("微软雅黑", 14)).grid(row=2)
Label(root,text="开始题号", font=("微软雅黑", 14)).grid(row=3)
Label(root,text="结束题号", font=("微软雅黑", 14)).grid(row=4)
defaultUrl = StringVar()
hustojurl=Entry(root, textvariable=defaultUrl, font=("微软雅黑", 14))
hustojurl.grid(row=2,column=1)
defaultsID = StringVar()
startId = Entry(root, textvariable=defaultsID, font=("微软雅黑", 14))
startId.grid(row=3,column=1)
defaulteID = StringVar()
endId = Entry(root, textvariable=defaulteID, font=("微软雅黑", 14))
endId.grid(row=4,column=1)
gotoButton = Button(root, text="开爬", font=("微软雅黑", 14), command=qaq)
gotoButton.grid(row=7, columnspan=2)
proLog.insert("end", getTime()+"启动程序\n")
proLog.insert("end", getTime()+"重要，启动前请先看帮助\n", "tagInfo")
root.config(menu=menubar)
root.mainloop()